package org.vectrics.history;


import java.util.Date;
import java.util.List;
import java.util.TreeSet;
import java.util.Collection;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import org.hibernate.Session;
import org.vectrics.history.ActivityDateCompare;
import org.vectrics.history.Activity;
import org.vectrics.hibernate.Filter;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.hibernate.HibernateUtil;
import org.vectrics.hibernate.Selector;
import org.vectrics.user.Person;
import org.vectrics.user.ServiceRequest;
import org.vectrics.user.ServiceRequestCriteria;
import org.vectrics.user.ServiceRequestSortOrder;
import org.vectrics.DataException;



public class HistoryPersistMgr extends HistoryProvider {
	private transient static Logger log = Logger.getLogger(HistoryPersistMgr.class);

	public HistoryPersistMgr() {
	}

	public Activity createHistory(String objectType, String objectId, String activityTypeCode,
	        Person person, String description) {
		Activity hist = null;
		try {
			Session session = ThreadProperties.getSession();
			hist = createHistory(session, objectType, objectId, activityTypeCode, person, description);
		}
		catch (Exception ex) {
			log.error("createHistory - exception", ex);
			throw new DataException(ex);
		}
		return(hist);
	}


	public Activity createHistory(Session session, String objectType, String objectId,
	        String activityTypeCode,
	        Person person, String description) throws DataException {
		Activity hist = new Activity();
	    ActivityType activityType = (ActivityType)session.load(ActivityType.class, activityTypeCode);

		log.debug("createHistory() - objectId = " + objectId);
		hist.setObjectId(objectId);
		hist.setObjectType(objectType);
		hist.setActivityType(activityType);
		hist.setPerson(person);
		hist.setDate(new Date());
		hist.setDescription(description);
		session.save(hist);
		return(hist);
	}

	public void clearObjectHistory(String objectType, String objectId) throws DataException {
		Session session = ThreadProperties.getSession();
		this.clearObjectHistory(session, objectType, objectId);

	}

	public void clearObjectHistory(Session session, String objectType, String objectId) {
		log.debug("clearObjectHistory()");
		Collection histList = findObjectHistoryEntries(session, objectType, objectId);
		Iterator iter = histList.iterator();
		while (iter.hasNext()) {
			Activity objHist = (Activity)iter.next();
			log.debug("clearObjectHistory() - deleting entry: " + objHist.getId());
			session.delete(objHist);
		}
	}


	public Collection findObjectHistoryEntries(String objectType, String objectId) {
		Collection entries = null;
		Session session = ThreadProperties.getSession();
		entries = findObjectHistoryEntries(session, objectType, objectId);
		return(entries);
	}


	public Collection findHistoryEntriesBy(Person person) throws DataException {
		Collection entries = null;
		try {
			Session session = ThreadProperties.getSession();
			entries = findHistoryEntriesBy(session, person.getId());
		}
		catch (Exception he) {
			throw new DataException(he);
		}
		return(entries);

	}


	public Collection findHistoryEntries(Date startDate, Date endDate) throws DataException {
		TreeSet sortedEntries = new TreeSet(new ActivityDateCompare());
		List entries = null;
		Session session = ThreadProperties.getSession();

		log.debug("findHistoryEntriesBy() - running hibernate query");
		entries = session.createQuery("from Activity as oh where (oh.date >= ?) and (oh.date <= ?) order by oh.date")
			.setDate(0, startDate)
			.setDate(1, endDate)
			.list();
		if (log.isEnabledFor(Level.DEBUG)) {
			log.debug("findHistoryEntriesBy() - number of elements found = " + entries.size());

		}

		log.debug("putting history elements in sortable container...");
		if (entries != null) {
			sortedEntries.addAll(entries);
		}


		return(sortedEntries);
	}



	public Collection findHistoryEntriesBy(Session session, Long personId) throws DataException {
		List entries = null;
		log.debug("findHistoryEntriesBy() - running hibernate query");
		entries = session.createQuery(
					"from Activity as oh where oh.person.id = ? order by oh.date")
					.setLong(0, personId.longValue())
					.list();

		if (log.isEnabledFor(Level.DEBUG)) {
			log.debug("findHistoryEntriesBy() - number of elements found = " + entries.size());

		}

		log.debug("putting history elements in sortable container...");
		TreeSet sortedEntries = new TreeSet(new ActivityDateCompare());
		if (entries != null) {
			sortedEntries.addAll(entries);
		}

		return(sortedEntries);
	}


	public Collection findObjectHistoryEntries(Session session, String objectType, String objectId) {
 		List entries = null;
		log.debug("findObjectHistoryEntries() - running hibernate query");
		entries = session.createQuery(
				"from Activity as oh where oh.objectType = ? and oh.objectId = ?")
				.setString(0, objectType)
				.setString(1, objectId)
				.list();

		if (log.isEnabledFor(Level.DEBUG)) {
			log.debug("findObjectHistoryEntries() - number of elements found = " + entries.size());

		}

		log.debug("putting history elements in sortable container...");
		TreeSet sortedEntries = new TreeSet(new ActivityDateCompare());
		if (entries != null) {
			sortedEntries.addAll(entries);
		}

		return(sortedEntries);
	}


	/*
	 * Save request from web user information
	 */
	public void saveServiceRequest(ServiceRequest serviceRequest) {
		log.debug("saveServiceRequest()");
		Session session = ThreadProperties.getSession();
		session.save(serviceRequest);
		log.debug("done with saveServiceRequest()");
	}


	private Filter getFilterForServiceRequestCriteria(ServiceRequestCriteria criteria,
			ServiceRequestSortOrder sort) {
		log.debug("getFilterForServiceRequestCriteria()");
		Filter filter = new Filter();
		filter.setConjunction(Selector.CONJUNTION_AND);
		filter.addFrom("ServiceRequest", "serviceRequest");

		if (sort != null)
		    filter.addOrderBy("serviceRequest.timeStamp");

		if (criteria.getDateStart() != null) {
			filter.getSelector().addParameterCondition("serviceRequest.timeStamp", ">=", criteria.getDateStart());
		}

		if (criteria.getDateEnd() != null) {
			filter.getSelector().addParameterCondition("serviceRequest.timeStamp", "<=", criteria.getDateEnd());
		}


		return(filter);
	}


	public List findServiceRequests(
			ServiceRequestCriteria criteria, ServiceRequestSortOrder sort, int start, int end) {
		List serviceRequests = null;
		Filter filter = getFilterForServiceRequestCriteria(criteria, sort);
		filter.addSelectField("distinct serviceRequest");
		serviceRequests = HibernateUtil.findElements(filter, start, end);

		return(serviceRequests);
	}


	public int findServiceRequestsCount(ServiceRequestCriteria criteria, int start, int end) {
		Filter filter = getFilterForServiceRequestCriteria(criteria, null);
		int count = HibernateUtil.findElementCount(filter, "serviceRequest");
		return(count);
	}


}
